home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Magazin/MacEasy 19
/
Mac Magazin and MacEasy Magazine CD - Issue 19.iso
/
Musik & Kunst
/
Ear Workout 2.1
/
source code
/
ear_sound.cp
< prev
next >
Wrap
Text File
|
1996-01-08
|
6KB
|
202 lines
#include <stdio.h>
#include <math.h>
#include <OSUtils.h>
#include <QuickDraw.h>
#include <Sound.h>
#define NEED_MAC_STUFF 1
#include "Ninkasi:C++ util:generic.h"
#include "Ninkasi:C++ util:complete_window.h"
#include "ear_defines.h"
#include "ear_decl.h"
#include "ear_prototypes.h"
// returns avg of left and right volumes;
// 256 = max normal vol
int
get_current_volume(SndChannelPtr snd_chan)
{
SndCommand my_snd_command;
union {
long the_volumes;
short vol[2];
} vol_data;
my_snd_command.cmd = getVolumeCmd;
my_snd_command.param2 = (long) &(vol_data.the_volumes);
SndDoImmediate(snd_chan,&my_snd_command);
return (int) (.5*(vol_data.vol[0]+vol_data.vol[1]));
}
void
set_volume(int new_volume,SndChannelPtr snd_chan)
{
SndCommand my_snd_command;
union {
long the_volumes;
short vol[2];
} vol_data;
my_snd_command.cmd = volumeCmd;
vol_data.vol[0] = new_volume;
vol_data.vol[1] = new_volume;
my_snd_command.param2 = vol_data.the_volumes;
SndDoImmediate(snd_chan,&my_snd_command);
}
// The first time this routine is called, everything is computed from
// scratch.
// On subsequent calls, the default behavior is to simply rescale the
// floating-point version of the waveform, and the "kind" parameter
// is ignored.
// To force a recalculation from scratch, set both have_wave_table
// and have_temp_wave_table to zero.
void
do_waveforms(
SndChannelPtr *my_snd_chan,
int kind,
double amplitude,
int chans_used,
unsigned char *wave_table,
double *temp_storage,
int wave_table_size)
{
dispose_of_chans(chans_used,my_snd_chan);
//..in case they were already installed
make_sound_channels(chans_used,init_chan_list,kind_of_chan_list,my_snd_chan);
if (!have_wave_table) {
make_wave_table(wave_table,temp_storage,kind,amplitude,wave_table_size,
!have_temp_wave_table);
have_wave_table = 1;
have_temp_wave_table = 1;
}
install_waveforms(chans_used,my_snd_chan,wave_table,wave_table_size,kind_of_chan_list);
}
void
play_chord(int notes_in_chord,
SndChannelPtr *my_snd_chan,
int *note,
int duration, //-- in half-milliseconds
int if_wait)
{
int delay_ticks,i;
SndCommand my_snd_cmd;
OSErr my_err;
set_up_sound();
for (i=0; i<=notes_in_chord-1; i++) {
my_snd_cmd.cmd = freqDurationCmd;
my_snd_cmd.param1 = duration;
my_snd_cmd.param2 = note[i]+pitch_offset;
my_err = SndDoCommand(my_snd_chan[i],&my_snd_cmd,FALSE);
if (my_err!=0) {
bail_out("error playing sound");
}
}
if (if_wait) {
delay_ticks = duration/33.33333;
delay_some(delay_ticks);
wait_until_chan_not_busy(my_snd_chan[notes_in_chord-1],1);
}
dispose_of_chans(chans_used,my_snd_chan);
// Let other programs have sound channels. Also, make sure
// sound channels are available for parts of this program
// that use other synthesizers other than the wavetable one.
}
void
wait_until_chan_not_busy(SndChannelPtr my_snd_chan,int max_secs)
{
unsigned long count;
int max_ticks;
OSErr my_err;
SCStatus my_sc_status;
max_ticks = max_secs*60;
count = 0;
do {
my_err = SndChannelStatus(my_snd_chan,sizeof(SCStatus),&my_sc_status);
delay_some(1); /* 1 tick = 1/60 sec */
++count;
} while(my_sc_status.scChannelBusy && count<max_ticks);
}
void
rest(int nhalf_ms)
{
delay_some((int) (nhalf_ms/33.33333));
}
void
delay_some(int nticks)
{
unsigned long delay_ticks,sys_time;
delay_ticks = nticks;
Delay(delay_ticks,(long *) &sys_time);
}
void
install_waveforms(int nchan,SndChannelPtr *my_snd_chan,
unsigned char *my_wave_table,int wave_table_size,short *kind_of_chan_list)
{
int i;
SndCommand my_snd_cmd;
OSErr my_err;
my_snd_cmd.cmd = waveTableCmd;
my_snd_cmd.param1 = wave_table_size;
my_snd_cmd.param2 = (long) my_wave_table;
for (i=0; i<nchan; i++) {
if (kind_of_chan_list[i]==waveTableSynth) {
if (!made_snd_chan[i]) bail_out("channel not made yet in install_waveforms");
my_err = SndDoCommand(my_snd_chan[i],&my_snd_cmd,FALSE);
if (my_err!=0) {
char s[200];
sprintf(s,"error in install_waveforms, i=%d, my_err=%d, my_snd_chan[i]=%08lx\n",
(int) i,(int) my_err,(long) my_snd_chan[i]);
bail_out(s);
}
}
}
}
void
make_sound_channels(
int chans_used,
long *init_chan_list,
short *kind_of_chan_list,
SndChannelPtr *my_snd_chan) /* array of pointers to sound channels */
{
int i;
OSErr my_err;
dispose_of_chans(chans_used,my_snd_chan);
for (i=0; i<chans_used; i++) {
my_snd_chan[i] = NULL; /* tells it I need a new channel allocated on heap */
my_err = SndNewChannel(&my_snd_chan[i],
kind_of_chan_list[i],init_chan_list[i],NULL);
if (my_err!=0) {
bail_out("error in SndNewChannel\n");
}
made_snd_chan[i] = 1;
}
}
void
dispose_of_chans(
int chans_used,
SndChannelPtr *my_snd_chan) /* array of pointers to sound channels */
{
int i;
OSErr my_err;
for (i=0; i<=chans_used-1; i++) {
if (made_snd_chan[i] && VALID_POINTER(my_snd_chan[i])) {
my_err = SndDisposeChannel(my_snd_chan[i],(Boolean) 1);
/* 0=await completion, 1=immediate return */
made_snd_chan[i] = 0;
my_snd_chan[i] = (SndChannelPtr) 0;
}
}
}